#include <unistd.h>
#include "custom/sys.h"
#include "application/video.h"
#include <stdlib.h>
#include <pthread.h>
#include "lvgl/lvgl.h"
#include "lvgl/examples/lv_examples.h"
#include "lvgl/demos/lv_demos.h"
#include "lv_drivers/sdl/sdl.h"
#include "lv_drivers/display/fbdev.h"
#include "lv_drivers/indev/mouse.h"
#include "lv_drivers/indev/mousewheel.h"
#include "lv_drivers/indev/evdev.h"
#include "lv_drv_conf.h"

static void hal_init(void);
static void *tick_thread(void *arg);

static void exit_callback(lv_event_t *event);

static Video *video;
static mutex ui_mutex;

int main(int argc, char **argv)
{
    char *file_name;
    (void)argc; /*Unused*/
    (void)argv; /*Unused*/

    if (argv[1] != NULL)
    {
        printf("File:%s\r\n", argv[1]);
        file_name = argv[1];
    }
    else
    {
        printf("Required file path\r\n");
        // return -1;
    }

    /*Initialize LVGL*/
    lv_init();

    /*Initialize the HAL (display, input devices, tick) for LVGL*/
    hal_init();

    video = new Video(exit_callback, ui_mutex, file_name);

    while (1)
    {
        ui_mutex.lock();
        uint32_t ms = lv_task_handler();
        ui_mutex.unlock();

        usleep(ms * 1000);
    }
    return 0;
}

/**
 * Initialize the Hardware Abstraction Layer (HAL) for the LVGL graphics
 * library
 */
static void hal_init(void)
{
#if USE_MONITOR || USE_SDL
    monitor_init();
#else
    fbdev_init();
#endif

    pthread_t id;

    /*创建函数线程，并且指定函数线程要执行的函数*/
    int res = pthread_create(&id, NULL, tick_thread, NULL);

    /*创建一个显示缓冲区*/
#if USE_SDL
    uint32_t disp_drv_width, disp_drv_height;
    disp_drv_width = SDL_HOR_RES;
    disp_drv_height = SDL_VER_RES;
    uint32_t fb_buff_size = disp_drv_width * disp_drv_height * 4;
#else
    uint32_t disp_drv_width, disp_drv_height, disp_drv_dpi;
    fbdev_get_sizes(&disp_drv_width, &disp_drv_height, &disp_drv_dpi);
    uint32_t fb_buff_size = disp_drv_width * disp_drv_height * 4;
#endif
    static lv_disp_draw_buf_t disp_buf;
    lv_color_t *buf1_1 = NULL, *buf1_2 = NULL;
    buf1_1 = (lv_color_t *)malloc(fb_buff_size);
    buf1_2 = (lv_color_t *)malloc(fb_buff_size);
    lv_disp_draw_buf_init(&disp_buf, buf1_1, buf1_2, fb_buff_size);

    /*Create a display*/
    static lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv); /*Basic initialization*/
    disp_drv.draw_buf = &disp_buf;

#if USE_SDL
    disp_drv.flush_cb = monitor_flush;
#else
    disp_drv.flush_cb = fbdev_flush;
#endif

    disp_drv.hor_res = disp_drv_width;
    disp_drv.ver_res = disp_drv_height;
    lv_disp_t *disp = lv_disp_drv_register(&disp_drv);

    /*主题*/
    lv_theme_t *th = lv_theme_default_init(disp,
                                           lv_palette_main(LV_PALETTE_BLUE),
                                           lv_palette_main(LV_PALETTE_RED),
                                           LV_THEME_DEFAULT_DARK,
                                           LV_FONT_DEFAULT);
    lv_disp_set_theme(disp, th);

    /*分组*/
    lv_group_t *g = lv_group_create();
    lv_group_set_default(g);

#if USE_SDL
    /* 添加鼠标作为输入设备使用'sdl_mouse_read'驱动程序读取PC的鼠标*/
    static lv_indev_drv_t indev_drv_1;
    lv_indev_drv_init(&indev_drv_1); /*Basic initialization*/
    indev_drv_1.type = LV_INDEV_TYPE_POINTER;

    /*这个函数将被定期调用(由库)来获取鼠标的位置和状态*/
    indev_drv_1.read_cb = sdl_mouse_read;
    lv_indev_t *mouse_indev = lv_indev_drv_register(&indev_drv_1);
#endif
/*键盘输入*/
#if USE_SDL
    static lv_indev_drv_t indev_drv_2;
    lv_indev_drv_init(&indev_drv_2);
    indev_drv_2.type = LV_INDEV_TYPE_KEYPAD;
    indev_drv_2.read_cb = sdl_keyboard_read;

    lv_indev_t *kb_indev = lv_indev_drv_register(&indev_drv_2);
    lv_indev_set_group(kb_indev, g);
#endif

/*event 输入*/
#if USE_EVDEV || USE_BSD_EVDEV
    evdev_init();
    static lv_indev_drv_t indev_drv;
    lv_indev_drv_init(&indev_drv);          /*Basic initialization*/
    indev_drv.type = LV_INDEV_TYPE_POINTER; /*See below.*/
    indev_drv.read_cb = evdev_read;         /*See below.*/

    /*Register the driver in LVGL and save the created input device object*/
    lv_indev_t *evdev_indev = lv_indev_drv_register(&indev_drv);
#endif
}

static void *tick_thread(void *arg)
{
    while (1)
    {
        usleep(5 * 1000);
        lv_tick_inc(5);
    }
    return ((void *)0);
}

static void exit_callback(lv_event_t *event)
{
    delete video;
    exit(0);
}